﻿using System;
using ilgolosone.DomainModel.Entities;
using ilgolosone.Persistence.NH.Data;
using ilgolosone.Persistence.NH.Data.Impl;
using ilgolosone.DomainModel.ValueObjects;
using NHibernate;
using NUnit.Framework;

namespace ilgolosone.Persistence.NH.UnitTests
{
    public class PersistenceFixtureBase
    {
        private static ISessionCreator _sessionCreator;

        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            _sessionCreator = new NHibernateStandardSessionCreator();
        }

        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            _sessionCreator = null;
        }
        
        [SetUp]
        public void TestSetUp()
        {
            _sessionCreator.GenerateSchema();
            LoadAllTestData();
        }

        /// <summary>
        /// Carica i dati di test relativi alle specialità
        /// </summary>
        private void LoadSpecialtyTestData()
        {
            ConsumeUOW(uow =>
            {
                ISession session = uow.CurrentSession;

                for (int i = 0; i < 5; i++)
                {
                    session.Save(new Specialty("Specialita" + i, "Descrizione" + i, @"C:\"));
                }

                uow.Commit();
            });
        }

        /// <summary>
        /// Carica tutti i dati di test...
        /// </summary>
        private void LoadAllTestData()
        {
            ConsumeUOW(uow=>
            {
               ISession session = uow.CurrentSession;

               for (int r = 0; r < 4; r++)
               {
                   // Aggiunta ristoranti di test
                   Restaurant rest = new Restaurant("Ristorante" + r)
                   {
                       AddressInfo = new AddressInfo(
                           "Address_" + r,
                           "12345",
                           "City_" + r,
                           "XX"
                       ),
                       ContactInfo = new ContactInfo(
                           string.Format("http://www.ristorante{0}.it", r),
                           string.Format("info@ristorante{0}.it", r),
                           "123456789"
                       )
                   };

                   // Tavoli del ristorante, con qualche prenotazione...
                   for (int t = 0; t < 3; t++)
                   {
                       Table table = new Table(rest, t + 2, TableLocations.Esterno, false);
                       session.Save(table);
                       rest.Tables.Add(table);

                       Reservation reservation = new Reservation(
                           DateTime.Today.AddDays(t),
                           DateTime.Today.AddDays(t).AddHours(20),
                           DateTime.Today.AddDays(t).AddHours(23),
                           table,
                           string.Format("cliente{0}@email{0}.it", t)
                       );
                       session.Save(reservation);
                       table.Reservations.Add(reservation);
                   }

                   // Specialità di test (due portate per specialità...)
                   for (int i = 0; i < 2; i++)
                   {
                       Specialty spec = new Specialty("Specialita" + i + r, "Descrizione_" + i + r, @"C:\");
                       session.Save(spec);

                       // Portate di test associate alla specialità
                       for (int j = 0; j < 2; j++)
                       {
                           Dish d = new Dish(
                               "Portata_" + j + i + r,
                               DishCategories.Pasta,
                               spec,
                               rest,
                               "Ingredienti_" + j + i + r,
                               (decimal)new Random().Next(5, 50)
                           );

                           session.Save(d);

                           // Aggiunta della portata al ristorante
                           rest.Dishes.Add(d);
                       }
                   }
                   session.Save(rest);
               }
               uow.Commit();
           });
        }

        protected void ConsumeUOW(Action<NHibernateUnitOfWork> action)
        {
            using (var uow = new NHibernateUnitOfWork(_sessionCreator))
            {
                uow.Start();
                action(uow);
            }
        }
    }
}